package com.cwd.arm.application.service.read;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cwd.arm.application.dto.ConfirmIncomeDto;
import com.cwd.arm.application.service.read.facade.ConfirmIncomeReadService;
import com.cwd.arm.common.util.BigDecimalUtil;
import com.cwd.arm.common.util.DateUtil;
import com.cwd.arm.infrastructure.dao.ConfirmIncomeDao;
import com.cwd.arm.infrastructure.dao.ProjectDao;
import com.cwd.arm.infrastructure.po.ConfirmIncomePo;
import com.cwd.arm.infrastructure.po.ProjectPo;
import com.cwd.arm.infrastructure.query.ConfirmIncomeDaoQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:确认收入
 * Created on 2021年11月16日
 *
 * @author yan
 */
@Repository
@Primary
public class ConfirmIncomeReadServiceImpl implements ConfirmIncomeReadService {

    @Autowired
    private ConfirmIncomeDao confirmIncomeDao;

    @Autowired
    private ProjectDao projectDao;

    @Override
    public ConfirmIncomeDto selectById(Long id) {
        return convertToDto(confirmIncomeDao.getById(id));
    }

    @Override
    public List<ConfirmIncomeDto> selectByProjectId(Long projectId) {
        ConfirmIncomeDaoQuery daoQuery = new ConfirmIncomeDaoQuery();
        daoQuery.setProjectId(projectId);
        List<ConfirmIncomeDto> confirmIncomeDtoList = selectByQuery(daoQuery);
        confirmIncomeDtoList = confirmIncomeDtoList.stream().sorted(Comparator.comparing(ConfirmIncomeDto::getConfirmDate)).collect(Collectors.toList());
        ProjectPo projectPo = projectDao.getById(projectId);
        BigDecimal contractAmount = BigDecimalUtil.hasRecord(projectPo.getCloseAmount())? projectPo.getCloseAmount(): projectPo.getContractAmount();
        BigDecimal confirmAmount = BigDecimal.ZERO;
        for(ConfirmIncomeDto confirmIncomeDto : confirmIncomeDtoList){
            confirmAmount = BigDecimalUtil.add(confirmIncomeDto.getConfirmAmount(),confirmAmount);
            confirmIncomeDto.setCompletionRate(BigDecimalUtil.div2(confirmAmount,contractAmount));
        }
        return confirmIncomeDtoList;
    }

    @Override
    public List<ConfirmIncomeDto> selectByQuery(ConfirmIncomeDaoQuery daoQuery) {
        return convertToDtoList(confirmIncomeDao.selectByQuery(daoQuery));
    }

    @Override
    public BigDecimal getRate(Long projectId, BigDecimal amount, Long confirmIncomeId, String date) throws Exception{
        BigDecimal confirmAmount = amount;
        Date confirmDate = DateUtil.strToDate(date);

        //对修改的处理
        if (confirmIncomeId != null && StringUtils.isNotEmpty(date)) {//对修改的处理,时间不传时也当新增,且默认为最晚的时间
            ConfirmIncomePo oldConfirmIncome = confirmIncomeDao.getById(confirmIncomeId);
            if (!DateUtil.isBeforeDate(confirmDate, oldConfirmIncome.getConfirmDate())
                    || DateUtil.isTheSameDate(confirmDate,oldConfirmIncome.getConfirmDate())) {//如果现在的日期在之前日期之后需要减去之前日期
                confirmAmount = BigDecimalUtil.sub(amount, oldConfirmIncome.getConfirmAmount());
            }
        }
        //已有记录要加上已有记录
        List<ConfirmIncomePo> confirmIncomePoList = getOldConfirmIncomePoList(projectId, confirmDate);
        if (CollectionUtils.isNotEmpty(confirmIncomePoList)) {
            BigDecimal oldConfirmAmountTotal = confirmIncomePoList.stream().map(ConfirmIncomePo::getConfirmAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            confirmAmount = BigDecimalUtil.add(confirmAmount, oldConfirmAmountTotal);
        }

        ProjectPo projectPo = projectDao.getById(projectId);
        BigDecimal contractAmount = BigDecimalUtil.hasRecord(projectPo.getCloseAmount())? projectPo.getCloseAmount(): projectPo.getContractAmount();
        return BigDecimalUtil.div2(confirmAmount, contractAmount);
    }

    @Override
    public BigDecimal getAmount(Long projectId, BigDecimal rate, Long confirmIncomeId, String date) throws Exception{
        BigDecimal confirmAmount = BigDecimal.ZERO;
        Date confirmDate = DateUtil.strToDate(date);

        //对修改的处理,时间不传时也当新增,且默认为最晚的时间
        if (confirmIncomeId != null && StringUtils.isNotEmpty(date)) {
            ConfirmIncomePo oldConfirmIncome = confirmIncomeDao.getById(confirmIncomeId);
            if (!DateUtil.isBeforeDate(confirmDate, oldConfirmIncome.getConfirmDate())
                    || DateUtil.isTheSameDate(confirmDate,oldConfirmIncome.getConfirmDate())) {
                confirmAmount = BigDecimalUtil.sub(confirmAmount, oldConfirmIncome.getConfirmAmount());
            }
        }

        //已有记录要加上已有记录
        List<ConfirmIncomePo> confirmIncomePoList = getOldConfirmIncomePoList(projectId, confirmDate);
        if (CollectionUtils.isNotEmpty(confirmIncomePoList)) {
            BigDecimal oldConfirmAmountTotal = confirmIncomePoList.stream().map(ConfirmIncomePo::getConfirmAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            confirmAmount = BigDecimalUtil.add(confirmAmount, oldConfirmAmountTotal);
        }

        ProjectPo projectPo = projectDao.getById(projectId);
        BigDecimal contractAmount = BigDecimalUtil.hasRecord(projectPo.getCloseAmount())? projectPo.getCloseAmount(): projectPo.getContractAmount();
        BigDecimal amount = contractAmount.multiply(rate);
        return amount.subtract(confirmAmount);
    }

    private List<ConfirmIncomePo> getOldConfirmIncomePoList(Long projectId, Date date) {
        ConfirmIncomeDaoQuery confirmIncomeDaoQuery = new ConfirmIncomeDaoQuery();
        confirmIncomeDaoQuery.setProjectId(projectId);
        confirmIncomeDaoQuery.setNow(date);
        return confirmIncomeDao.selectByQuery(confirmIncomeDaoQuery);
    }

    private ConfirmIncomeDto convertToDto(ConfirmIncomePo po) {
        ConfirmIncomeDto dto = new ConfirmIncomeDto();
        BeanUtils.copyProperties(po, dto);
        return dto;
    }

    private List<ConfirmIncomeDto> convertToDtoList(List<ConfirmIncomePo> poList) {
        return poList.stream().map(po -> convertToDto(po)).collect(Collectors.toList());
    }

}
